package org.zhouhe.modules.user.service;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Service;
import org.zhouhe.base.BaseService;
import org.zhouhe.page.PageUtil;
import org.zhouhe.vo.Menu;
import org.zhouhe.vo.Role;
import org.zhouhe.vo.RoleMenu;
import org.zhouhe.vo.User;
import org.zhouhe.vo.UserRole;

@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserService extends BaseService {
	public void saveUser(User user) {
		if (user.getUserId() == null) {
			user.setInsertTime(new Timestamp(new Date().getTime()));
			dao.save(user);
		} else {
			User bean = (User) dao.get(User.class, user.getUserId());
			bean.setRealName(user.getRealName());
			bean.setInsertTime(new Timestamp(new Date().getTime()));
			dao.update(bean);
		}
	}

	public void updatePassword(Integer userId, String password) {
		User user = (User) dao.get(User.class, userId);
		user.setLoginPwd(password);
		dao.save(user);
	}

	public void saveOrUpdateRole(Role role) {

	}

	public void deleteUser(User user) {
		dao.delete(user);
	}

	public User getUserDetail(Integer userId) {
		User user = (User) dao.get(User.class, userId);
		user.setLoginPwd(null);
		return user;
	}

	public Map<String, ?> login(User user) {
		Map<String, Object> userInfoMap = new HashMap<String, Object>();
		List list = dao.find("from User where loginName=? and loginPwd=?", user.getLoginName(), user.getLoginPwd());
		if (list.size() == 0)
			return null;
		User u = (User) list.get(0);
		userInfoMap.put("user", u);
		Iterator<UserRole> it = u.getUserRoles().iterator();
		List<Integer> roleIdList = new ArrayList<Integer>();
		while (it.hasNext()) {
			UserRole ur = it.next();
			roleIdList.add(ur.getRole().getRoleId());
		}
		userInfoMap.put("roleIdList", roleIdList);
		return userInfoMap;
	}

	public PageUtil findUserByPage(PageUtil pageUtil, User user) {
		if (pageUtil == null) {
			pageUtil = new PageUtil();
		}
		if (user == null) {
			user = new User();
		}
		List<Object> paramList = new ArrayList<Object>();
		StringBuilder from = new StringBuilder("from User where 1=1 ");
		String loginName = user.getLoginName();
		if (loginName != null && loginName.trim().length() > 0) {
			from.append(" and loginName like ?  ");
			paramList.add("%" + loginName + "%");
		}
		String realName = user.getRealName();
		if (realName != null && realName.trim().length() > 0) {
			from.append(" and realName like ?  ");
			paramList.add("%" + realName + "%");
		}
		from.append(" order by userId desc");
		pageUtil.setHQL(" ", from.toString(), paramList);
		return dao.findByPage(pageUtil);
	}

	/**********************************/
	public List<Role> getRoleList() {
		return (List<Role>) dao.find("from Role order by roleId desc");
	}

	public void configUserRoles(User user, Integer[] roleId) {
		if (roleId != null && roleId.length > 0) {
			dao.executeUpdate("delete from UserRole where user.userId=" + user.getUserId());
			for (Integer rid : roleId) {
				Role role = new Role();
				role.setRoleId(rid);
				UserRole userRole = new UserRole();
				userRole.setRole(role);
				userRole.setUser(user);
				dao.save(userRole);
			}
		}
	}

	public Integer[] findRoleIdsByUser(Integer userId) {
		List list = dao.find("select role.roleId from UserRole where user.userId=" + userId);
		Integer[] rs = new Integer[list.size()];
		for (int i = 0; i < list.size(); i++) {
			rs[i] = new Integer(list.get(i).toString());
		}
		return rs;
	}

	public void saveRole(Role role) {
		if (role.getRoleId() == null) {
			dao.save(role);
		} else {
			Role bean = (Role) dao.get(Role.class, role.getRoleId());
			bean.setRoleName(role.getRoleName());
			dao.save(bean);
		}
	}

	public void deleteRole(Role role) {
		dao.delete(role);
	}

	public List<Menu> findAllMenus() {
		List<Menu> menuList = dao.find("from Menu where menu is null order by menu.menuId asc");
		return menuList;
	}

	public Integer[] findLeafMenuIdsByRole(Role role) {
		List list = dao.find("select menu.menuId from RoleMenu where size(menu.menus)=0 and role.roleId=" + role.getRoleId());
		Integer[] rs = new Integer[list.size()];
		for (int i = 0; i < list.size(); i++) {
			rs[i] = new Integer(list.get(i).toString());
		}
		return rs;
	}

	public List<Integer> findMenusByRoleIds(Integer[] roleIds) {
		if(roleIds == null || roleIds.length == 0){
			return new ArrayList<Integer>();
		}
		final StringBuilder sql = new StringBuilder();
		sql.append("select distinct m.menu_id ");
		sql.append("from menu m, role_menu rm, role r ");
		sql.append("where m.menu_id=rm.menu_id and rm.role_id=r.role_id ");
		sql.append("and r.role_id in(" + StringUtils.join(roleIds, ",") + ") ");
		List<Integer> list = dao.getHibernateTemplate().executeFind(new HibernateCallback<List<Integer>>() {
			public List<Integer> doInHibernate(Session session) throws HibernateException, SQLException {
				return session.createSQLQuery(sql.toString()).list();
			}
		});
		return list;
	}

	public List<Menu> findMenusByUserId(Integer userId) {
		Integer[] roleIds = this.findRoleIdsByUser(userId);
		List<Integer> userMenuIdList = this.findMenusByRoleIds(roleIds);
		List<Menu> menuList = this.findAllMenus();
		for (Menu m1 : menuList) {
			Set<Menu> subMenus = m1.getMenus();
			List<Menu> removeLst = new ArrayList<Menu>();
			if (subMenus != null) {
				for (Menu m2 : subMenus) {
					if (!userMenuIdList.contains(m2.getMenuId())) {
						removeLst.add(m2);
					}
				}
				subMenus.removeAll(removeLst);
			}
		}
		return menuList;
	}

	public void configRoleMenus(Role role, Integer[] menuId) {
		if (menuId != null && menuId.length > 0) {
			dao.executeUpdate("delete from RoleMenu where role.roleId=" + role.getRoleId());
			for (Integer mid : menuId) {
				Menu menu = new Menu();
				menu.setMenuId(mid);
				RoleMenu roleMenu = new RoleMenu();
				roleMenu.setRole(role);
				roleMenu.setMenu(menu);
				dao.save(roleMenu);
			}
		}
	}

	public void test(PageUtil pageUtil) {
		this.findAllMenus();
	}
}
